package top.whysu.gps.service.navigation.impl;

import com.alibaba.fastjson.JSON;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import top.whysu.gps.constant.CodeConstant;
import top.whysu.gps.constant.Constant;
import top.whysu.gps.constant.DataDictionary;
import top.whysu.gps.constant.SystemConfigKey;
import top.whysu.gps.dao.gps.RouteCurrentDao;
import top.whysu.gps.dto.navigation.CurrentRouteAddModifyDTO;
import top.whysu.gps.exception.BusinessException;
import top.whysu.gps.po.navigation.RouteCurrentPO;
import top.whysu.gps.service.navigation.RouteCurrentService;
import top.whysu.gps.service.system.AccountService;
import top.whysu.gps.service.system.SystemConfigService;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 当前航线
 */
@Service("RouteCurrentServiceImpl")
public class RouteCurrentServiceImpl implements RouteCurrentService {

    private static final Logger LOGGER = LoggerFactory.getLogger(RouteCurrentServiceImpl.class);
    @Resource
    private RouteCurrentDao routeCurrentDao;
    @Resource
    private AccountService accountService;
    @Resource
    private SystemConfigService systemConfigService;

    @Override
    public List<RouteCurrentPO> selectList() {
        return routeCurrentDao.queryAll(null);
    }

    @Override
    public BigDecimal wholeAddModify(CurrentRouteAddModifyDTO addModifyDTO) {
        // 设备id
        BigDecimal id = addModifyDTO.getId();
        // 校验
        verify(addModifyDTO);
        // 当前操作用户
        String currentUser = accountService.getCurrentLoginUser();

        RouteCurrentPO po = new RouteCurrentPO();
        BeanUtils.copyProperties(addModifyDTO, po);
        // 时间
        Date currentDate = new Date();
        po.setUpdateBy(currentUser);
        po.setUpdateTime(currentDate);
        // 速度如果为空，设置为0
        if (StringUtils.isBlank(addModifyDTO.getSpeed())) {
            po.setSpeed("0");
        }
        if (id != null) {
            // 编辑
            po.setId(id);
            routeCurrentDao.update(po);
        } else {
            // 新增
            if (addModifyDTO.getPreId() != null) {
                // 如果有排序的话，把这个id后面的数据先查询出来，删掉后重新添加
                List<RouteCurrentPO> preList = routeCurrentDao.queryListAfterId(addModifyDTO.getPreId());
                // 先删除
                if (CollectionUtils.isNotEmpty(preList)) {
                    List<BigDecimal> deleteList = preList.stream().map(RouteCurrentPO::getId).collect(Collectors.toList());
                    routeCurrentDao.batchDelete(deleteList);
                }
                // 先增加这个点
                po.setRouteState(DataDictionary.RouteState.WAIT_FOR_SEND);
                po.setCreateBy(currentUser);
                po.setCreateTime(currentDate);
                routeCurrentDao.insert(po);
                // 新增之前被删除的点
                if (CollectionUtils.isNotEmpty(preList)) {
                    // 是否将其后的状态都置为等待发送
                    String resetFlag = systemConfigService.getConfig(SystemConfigKey.Common.COMMON_RESET_STATUS_AFTER_ADD);
                    if (String.valueOf(DataDictionary.YesOrNo.YES).equals(resetFlag)) {
                        preList.forEach(it -> {
                            // 置为等待发送
                            it.setRouteState(DataDictionary.RouteState.WAIT_FOR_SEND);
                        });
                    }
                    routeCurrentDao.batchInsert(preList);
                }
            } else {
                // 直接新增就好
                po.setRouteState(DataDictionary.RouteState.WAIT_FOR_SEND);
                po.setCreateBy(currentUser);
                po.setCreateTime(currentDate);
                routeCurrentDao.insert(po);
            }
            return po.getId();
        }
        return id;
    }

    @Override
    public void deleteCurrentRoute(BigDecimal id) {
        if (id == null) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "请指定需要删除的航线！");
        }
        routeCurrentDao.deleteById(id);
    }

    @Override
    public void wholeSetCurrentRoute(List<BigDecimal> routIdList) {
        if (CollectionUtils.isEmpty(routIdList)) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "请指定需要设定的航线！");
        }
        // 将选中的航线置为"等待发送"
        routeCurrentDao.updateRangeRouteState(routIdList, DataDictionary.RouteState.WAIT_FOR_SEND);
    }

    @Override
    public void batchDeleteCurrentRoute(List<BigDecimal> deleteIdList) {
        if (CollectionUtils.isEmpty(deleteIdList)) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "请指定需要删除的航线！");
        }
        // 批量删除
        routeCurrentDao.batchDelete(deleteIdList);
    }

    @Override
    public RouteCurrentPO getWanderCoordinate() {
        // 查询正在发送的一条航线
        RouteCurrentPO currentPO = routeCurrentDao.getSendingRoute();
        if (currentPO == null) {
            // 如果为空，查询最后一条状态为“已发送”的航线
            currentPO = routeCurrentDao.getLastByRouteState(DataDictionary.RouteState.HAS_BEEN_SEND);
            if (currentPO == null) {
                // 如果为空，则查询最新一条状态为“等待发送”的航线
                currentPO = routeCurrentDao.getNewestByRouteState(DataDictionary.RouteState.WAIT_FOR_SEND);
            }
        }
        return currentPO;
    }

    @Override
    public void updateNavigationState(BigDecimal routeId, Integer routeState) {
        RouteCurrentPO updatePO = new RouteCurrentPO();
        updatePO.setId(routeId);
        updatePO.setRouteState(routeState);
        routeCurrentDao.update(updatePO);
    }

    @Override
    public void batchInsert(List<RouteCurrentPO> routeList) {
        if (CollectionUtils.isNotEmpty(routeList)) {
            // 批量更新
            List<RouteCurrentPO> list = new ArrayList<>();
            for (int i = 1, len = routeList.size(); i <= len; i++) {
                list.add(routeList.get(0));
                routeList.remove(0);
                // 一次最多插入500条
                if (i % 500 == 0 || i == len) {
                    routeCurrentDao.batchInsert(list);
                    list.clear();
                }
            }
        } else {
            LOGGER.error("批量插入线路，集合为空");
        }
    }

    @Override
    public RouteCurrentPO getSelectedPoint() {
        // 查询当前模式
        Integer mode = Integer.valueOf(systemConfigService.getConfig(SystemConfigKey.CURRENT_MODE));
        // 是否手动模式
        Integer byHandMode = Integer.valueOf(systemConfigService.getConfig(SystemConfigKey.Common.BY_HAND));
        if (DataDictionary.Mode.ANCHOR == mode) {
            // 锚泊模式
            if (DataDictionary.YesOrNo.YES.equals(byHandMode)) {
                return JSON.parseObject(systemConfigService.getConfig(SystemConfigKey.Anchor.ANCHOR_POINT_BY_HAND), RouteCurrentPO.class);
            } else {
                return this.getWanderCoordinate();
            }
        } else if (DataDictionary.Mode.SINGLE_CIRCLE == mode) {
            // 单点模式
            if (DataDictionary.YesOrNo.YES.equals(byHandMode)) {
                return JSON.parseObject(systemConfigService.getConfig(SystemConfigKey.Single.SINGLE_POINT_BY_HAND), RouteCurrentPO.class);
            } else {
                return this.getWanderCoordinate();
            }
        } else {
            throw new BusinessException(CodeConstant.Http.EXECUTE_FAIL, "不支持的模式！");
        }
    }

    /**
     * 校验
     */
    private void verify(CurrentRouteAddModifyDTO dto) {
        if (dto.getLongitude().length() > 15) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "经度长度不能大于15字节");
        }
        if (dto.getLatitude().length() > 15) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "纬度长度不能大于15字节");
        }
        if (!Constant.Longitude.EAST.equals(dto.getLongitudeType()) && !Constant.Longitude.WEST.equals(dto.getLongitudeType())) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "经度类型错误！");
        }
        if (!Constant.Latitude.NORTH.equals(dto.getLatitudeType()) && !Constant.Latitude.SOUTH.equals(dto.getLatitudeType())) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "纬度类型错误！");
        }
        if (StringUtils.isNotBlank(dto.getSpeed()) && !verifySpeed(dto.getSpeed())) {
            throw new BusinessException(CodeConstant.Http.INFO_ERROR, "速度取值范围是000.0~999.9");
        }
    }

    /**
     * 经度和纬度，格式ddmm.mmmmmm
     */
    private static boolean verifyDegrees(String str) {
        // 整数位最大4位，可以0开头，小数位最大6位
        Pattern pattern = Pattern.compile("^[0-9]\\d{0,3}(\\.\\d{1,6})?$");
        Matcher match = pattern.matcher(str);
        return match.matches();
    }

    /**
     * 速度，值为000.0~999.9
     */
    private static boolean verifySpeed(String str) {
        // 整数位最大3位，可以0开头，小数位最大6位
        Pattern pattern = Pattern.compile("^[0-9]\\d{0,2}(\\.\\d{1})?$");
        Matcher match = pattern.matcher(str);
        return match.matches();
    }

    /**
     * 重新排序
     */
    private void reOrder(BigDecimal preId, BigDecimal currentId) {
        if (preId == null || currentId == null) {
            LOGGER.error("preId为空，currentId为空");
            return;
        }
        // 节点是否存在
        RouteCurrentPO prePO = routeCurrentDao.queryById(preId);
        if (prePO == null) {
            LOGGER.error("上一个节点不存在！preId: {}", preId);
            return;
        }
        // 查询这个节点前的航线点，重新排序


    }
}
